<?php

namespace App\Common\Cache;

use EasySwoole\ORM\DbManager;

use App\Common\RedisCache;
use App\Common\Tools;
use App\Model\Article\ {
    Nav as NavModel,
    Article as ArticleModel
};

/**
 * @description: 文章缓存
 */
class ArticleCache extends Cache
{
    /**
     * @description: 删除缓存
     * @param {*}
     * @return {*}
     */    
    public function del($args)
    {
        if ($this->cache) {
            switch ($args['func']) {
                case 'afterCreate':
                    $this->afterCreate($args['param']);
                    break;
                case 'afterMofidyDisplay':
                    $this->afterMofidyDisplay($args['param']);
                    break;
                case 'beforeDelete':
                    $this->beforeDelete($args['param']);
                    break;
            }
        }
    }

    /**
     * @description: 创建后
     * @param array $param 保存内容
     * @return {*}
     */
    protected function afterCreate($param)
    {
        if (Tools::hasValue($param, 'id')) {
            $art  = DbManager::getInstance()->invoke(function ($client) use ($param) {
                $model = ArticleModel::invoke($client);
                return $model->field('id,update_time,display')->get($param['id'])->toArray();
            });
            $key1 = $this->calluteTimeNewsKey($art);
            $key2 = $this->calluteHomeNewsKey($param['id']);
            $keys = array_merge($key1, $key2, ['article:' . $param['id']]);
        } else {
            $keys = [
                'article:home:news',
                'article:home:week',
                'article:home:month',
            ];
        }
        $key1 = $this->getDelNavsKeys($param['navs_id']);
        $keys = array_merge($keys, $key1);
        RedisCache::del($keys);
    }

    /**
     * @description: 修改显示后
     * @param {*} $param
     * @return {*}
     */
    protected function afterMofidyDisplay($param)
    {
        $art  = DbManager::getInstance()->invoke(function ($client) use ($param) {
            $model = ArticleModel::invoke($client);
            return $model->field('id,update_time,display')->get($param['id'])->toArray();
        });
        $key1 = $this->calluteTimeNewsKey($art);
        $key2 = $this->calluteHomeNewsKey($param['id']);
        $key3 = $this->getDelNavsKeys($param['navs_id']);
        $keys = array_merge($key1, $key2, $key3);

        RedisCache::del($keys);
    }

    /**
     * @description: 删除前
     * @param {*} $param
     * @return {*}
     */
    protected function beforeDelete($param)
    {
        $arts = DbManager::getInstance()->invoke(function ($client) use ($param) {
            $model = ArticleModel::invoke($client);
            $ids   = is_numeric($param['id']) ? array($param['id']) : $param['id'];
            return $model->field('id,display,navs_id,update_time')->all(['id' => [$ids, 'in']])->toArray();
        });
        $keys = [];
        foreach ($arts as $art) {
            $key1 = $this->calluteTimeNewsKey($art);
            $key2 = $this->getDelNavsKeys($art['navs_id']);
            $key3 = ['article:' . $art['id']];
            $keys = array_merge($key1, $key2, $key3);
        }
        $key4 = $this->calluteHomeNewsKey($param['id']);
        $keys = array_unique(array_merge($keys, $key4));
        RedisCache::del($keys);
    }

    /**
     * @description: 计算文章是否在周/月缓存中
     * @param array $art 文章数据
     * @return {*}
     */
    protected function calluteTimeNewsKey($art)
    {
        $keys = [];
        if ($art['display'] == 1) {
            $keys[] = 'article:' . $art['id'];
        }
        $w    = date('w');
        $w    = $w ? ($w - 1) : 6;
        $week = strtotime(date('Y-m-d') . ' - ' . $w . 'day');
        if (strtotime($art['update_time']) >= $week) {
            $keys[] = 'article:home:week';
        }
        $month = strtotime(date('Y-m-01'));
        if (strtotime($art['update_time']) >= $month) {
            $keys[] = 'article:home:month';
        }
        return $keys;
    }

    /**
     * @description: 计算文章是否在首页最新文章缓存中
     * @param int|array $artid 文章id
     * @return {*}
     */
    protected function calluteHomeNewsKey($artid)
    {
        $keys = [];
        $news = DbManager::getInstance()->invoke(function ($client){
            $model = ArticleModel::invoke($client);
            return $model->scopWhere()->order('update_time', 'desc')->limit(15)->column('id');
        });
        $ids = is_numeric($artid) ? array($artid) : $artid;
        if (array_intersect($ids, $news)) {
            $keys[] = 'article:home:news';
        }
        return $keys;
    }
    
    /**
     * @description: 获取某一文章分类下需要删除的文章相关key
     * @param int $navId 文章分类id
     * @return {*}
     */
    public function getDelNavsKeys($navId)
    {
        $keys = [];
        $path = DbManager::getInstance()->invoke(function ($client) use ($navId) {
            $model = NavModel::invoke($client);
            return $model->where('id', $navId)->val('path');
        });
        if ($path) {
            $paths = explode(':', $path);
            foreach ($paths as $val) {
                $keys[] = 'nav:' . $val . ':newArticle';
                $pkeys  = RedisCache::keys('nav:' . $val . ':page:*');
                $keys   = array_merge($keys, $pkeys);
            }
        }
        return $keys;
    }
}